#ifndef _MutexLock_H
#define _MutexLock_H

#include<pthread.h>
#include <sys/syscall.h>
#include <unistd.h>

class MutexLock
{
public:
    MutexLock() { pthread_mutex_init(&mutex_, nullptr); }

    ~MutexLock() { pthread_mutex_destroy(&mutex_);}

    void lock()
    {
        //holder_ = gettid();
        pthread_mutex_lock(&mutex_);
    }

    void unlock()
    { 
        pthread_mutex_unlock(&mutex_); 
        //holder_ = 0;
    }

    pthread_mutex_t* get() { return &mutex_; }

    //pid_t holder_;

    //pid_t gettid() { return static_cast<pid_t>(::syscall(SYS_gettid)); }

private:

    friend class Condition;
    pthread_mutex_t mutex_;

}; // class MutexLock end

class Condition
{
public:
    Condition(MutexLock &mutex_) : mutex(mutex_) { pthread_cond_init(&pcond_, nullptr);}

    ~Condition() { pthread_cond_destroy(&pcond_); }

    void wait() { pthread_cond_wait(&pcond_, mutex.get()); }

    void notify() { pthread_cond_signal(&pcond_); }

    void notifyAll() { pthread_cond_broadcast(&pcond_); }

private:
    MutexLock &mutex;
    pthread_cond_t pcond_;

}; // class Condition end

class MutexLockGuard
{
public:
    MutexLockGuard(MutexLock &mutex_) : mutex(mutex_) { mutex.lock(); }

    ~MutexLockGuard() { mutex.unlock(); }

private:
    MutexLock &mutex;

}; // class MutexLockGuard end

#endif